/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						     campaign_file_ref.cpp

	$Header: /game/campaign_file_ref.cpp $

	$NoKeywords: $

 ************************************************************************/

#include "precompiled.h"
#include "campaign_file_ref.h"

#include "sized_int_types.h"
#include "streambuf_operators.h"

// --------------------------------------------------------------------------
// Unnamed namespace
// --------------------------------------------------------------------------

namespace
{

	// --------------------------------------------------------------------------
	// t_file_name_body class
	// --------------------------------------------------------------------------

	class t_file_name_body : public t_campaign_file_ref_body
	{
	public:
		// Constructor
		explicit t_file_name_body( std::string const & file_name );

		// Member functions
		virtual void	accept( t_accessor & accessor ) const;

	private:
		// Data members
		std::string	m_file_name;
	};

	// --------------------------------------------------------------------------
	// t_file_name_body members
	// --------------------------------------------------------------------------

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	t_file_name_body::t_file_name_body( std::string const & file_name )
		:	m_file_name( file_name )
	{
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	void t_file_name_body::accept( t_accessor & accessor ) const
	{
		accessor.access( m_file_name );
	}

	// --------------------------------------------------------------------------
	// t_standard_campaign_id_body
	// --------------------------------------------------------------------------

	class t_standard_campaign_id_body : public t_campaign_file_ref_body
	{
	public:
		// Constructor
		explicit t_standard_campaign_id_body( t_standard_campaign_id id );

		// Member functions
		virtual void	accept( t_accessor & accessor ) const;

	private:
		// Data members
		t_standard_campaign_id	m_id;
	};

	// --------------------------------------------------------------------------
	// t_standard_campaign_id_body members
	// --------------------------------------------------------------------------

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	t_standard_campaign_id_body::t_standard_campaign_id_body(
		t_standard_campaign_id	id )
		:	m_id( id )
	{
		assert( id >= 0 && id < k_standard_campaign_count );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	void t_standard_campaign_id_body::accept( t_accessor & accessor ) const
	{
		accessor.access( m_id );
	}

	// --------------------------------------------------------------------------
	// t_write_helper class
	// --------------------------------------------------------------------------

	class t_write_helper : private t_campaign_file_ref_accessor
	{
	public:
		// Constructor
		explicit t_write_helper( std::streambuf & stream );

		// Operator
		bool	operator()( t_campaign_file_ref_body const & body );

	private:
		// Data members
		std::streambuf &	m_stream;
		bool				m_result;

		// Member functions
		virtual void	access( std::string const & file_name );
		virtual void	access( t_standard_campaign_id campaign_id );
	};

	// --------------------------------------------------------------------------
	// t_write_helper members
	// --------------------------------------------------------------------------

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	t_write_helper::t_write_helper( std::streambuf & stream )
		:	m_stream( stream )
	{
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	bool t_write_helper::operator()( t_campaign_file_ref_body const & body )
	{
		m_result = false;
		body.accept( *this );
		return m_result;
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	void t_write_helper::access( std::string const & file_name )
	{
		put< t_uint8 >( m_stream, false );
		if ( !write_string16( m_stream, file_name ) )
			return;
		m_result = true;
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	void t_write_helper::access( t_standard_campaign_id campaign_id )
	{
		put< t_uint8 >( m_stream, true );
		if ( !write_string16( m_stream, get_keyword( campaign_id ) ) )
			return;
		m_result = true;
	}

} // Unnamed namespace

// --------------------------------------------------------------------------
// t_campaign_file_ref_accessor members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_campaign_file_ref_accessor::access( std::string const & file_name )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_campaign_file_ref_accessor::access( t_standard_campaign_id id )
{
}

// --------------------------------------------------------------------------
// t_campaign_file_ref members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_campaign_file_ref::t_campaign_file_ref( std::string const & file_name )
	:	m_body_ptr( new t_file_name_body( file_name ) )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_campaign_file_ref::t_campaign_file_ref( t_standard_campaign_id id )
	:	m_body_ptr( new t_standard_campaign_id_body( id ) )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_campaign_file_ref::read( std::streambuf & stream )
{
	bool standard_campaign = get< t_uint8 >( stream ) != 0;
	if ( standard_campaign )
	{
		std::string keyword;
		if ( !read_string16( stream, keyword ) )
			return false;

		t_standard_campaign_id campaign_id = get_standard_campaign_id( keyword );
		if ( campaign_id < 0 || campaign_id >= k_standard_campaign_count )
			return false;

		m_body_ptr = new t_standard_campaign_id_body( campaign_id );
	}
	else
	{
		std::string file_name;
		if ( !read_string16( stream, file_name ) )
			return false;

		m_body_ptr = new t_file_name_body( file_name );
	}

	return true;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
bool t_campaign_file_ref::write( std::streambuf & stream ) const
{
	assert( m_body_ptr.get() != 0 );
	t_write_helper do_write( stream );
	return do_write( *m_body_ptr );
}
